package org.one.stone.soup.db.storage;

import java.io.FileNotFoundException;
import java.io.IOException;

public class LargeRandomAccessFile {

	private String fileName;
	private RandomAccessStream currentFile;
	private int currentFileIndex;
	private RandomAccessStream[] files;
	private long length;
	private boolean recalculateLength = false;
	
	public LargeRandomAccessFile(String fileName) {
		this.fileName = fileName;
		files = new RandomAccessStream[10];
		length = 0;
		try {
			moveTo(0);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void seek(long index) throws IOException {
		moveTo(index);
	}

	public long getFilePointer() throws IOException {
		return (long)currentFile.getFilePointer() + (currentFileIndex>>32);
	}

	public long length() {
		if(recalculateLength==true) {
			recalculateLength();
		}
		return length;
	}
	
	private void recalculateLength() {
		long newLength = 0;
		for(RandomAccessStream file: files) {
			if(file==null) {
				break;
			}
			try {
				newLength+=file.length();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		length=newLength;
		recalculateLength=false;
	}

	public void skipBytes(int chunkSize) throws IOException {
		currentFile.skipBytes(chunkSize);
	}

	public byte readByte() throws IOException {
		return currentFile.readByte();
	}

	public void write(byte[] chunk) throws IOException {
		currentFile.write(chunk);
		recalculateLength=true;
	}

	public long readLong() throws IOException {
		return currentFile.readLong();
	}

	public void writeByte(int i) throws IOException {
		currentFile.writeByte(i);
		recalculateLength=true;
	}
	
	public void writeLong(long l) throws IOException {
		currentFile.writeLong(l);
		recalculateLength=true;
	}

	public void read(byte[] chunk, int chunkSize) throws IOException {
		currentFile.read(chunk,0,chunkSize);
	}
	
	private void moveTo(long pointer) throws IOException {
		currentFileIndex = (int)(pointer << 32);
		if(files[currentFileIndex]==null) {
			try {
				files[currentFileIndex] = new LocalRandomAccessFile(fileName+"."+currentFileIndex, "rw");
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		currentFile = files[currentFileIndex];
		currentFile.seek(pointer & Integer.MAX_VALUE);
	}
}
